package com.nit.lab.vote.service.vote.impl;

import com.nit.lab.vote.dto.system.TokenDTO;
import com.nit.lab.vote.dto.utils.*;
import com.nit.lab.vote.dto.vote.ProjectDTO;
import com.nit.lab.vote.dto.vote.UPDTO;
import com.nit.lab.vote.entity.vote.ProjectEntity;
import com.nit.lab.vote.dto.vote.ProjectDTO;
import com.nit.lab.vote.entity.vote.CandidateEntity;
import com.nit.lab.vote.entity.vote.ProjectEntity;
import com.nit.lab.vote.entity.vote.UPEntity;
import com.nit.lab.vote.mapper.vote.ProjectMapper;
import com.nit.lab.vote.service.vote.ProjectService;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.apache.ibatis.annotations.Param;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
public class ProjectServiceImpl implements ProjectService {
    @Autowired(required = false)
    private ProjectMapper projectMapper;

    @Override
    public TableRspDTO listAll(TableReqDTO tableReqDTO) throws Exception {
        String stateStr = tableReqDTO.parseQueryParam("state");
        Long state = stateStr != null ? Long.valueOf(stateStr) : null;
        String projectTypeStr = tableReqDTO.parseQueryParam("projectType");
        Long projectType = projectTypeStr != null ? Long.valueOf(projectTypeStr) : null;
        Long count = projectMapper.count4Table1(
                tableReqDTO.parseQueryParam("projectName"),
                tableReqDTO.parseQueryParam("sponsor"),
                projectType,
                state
        );
        PagingDTO pagingDTO = new PagingDTO(
                tableReqDTO.getPageNo(),
                tableReqDTO.getPageSize(),
                count,
                projectMapper.listAll(
                        tableReqDTO.parseQueryParam("projectName"),
                        tableReqDTO.parseQueryParam("sponsor"),
                        projectType,
                        state,
                        tableReqDTO.getStart(),
                        tableReqDTO.getPageSize(),
                        tableReqDTO.getSortField(),
                        tableReqDTO.getSortOrder()));
        return new TableRspDTO(pagingDTO);
    }

    @Override
    public TableRspDTO listUserProject(Long userId, TableReqDTO tableReqDTO) throws Exception {
        String stateStr = tableReqDTO.parseQueryParam("state");
        Long state = stateStr != null ? Long.valueOf(stateStr) : null;
        Long count = projectMapper.count4Table(
                userId,
                tableReqDTO.parseQueryParam("projectName"),
                tableReqDTO.parseQueryParam("sponsor"),
                tableReqDTO.parseQueryParam("type"),
                tableReqDTO.parseQueryParam("subject"),
                state
        );
        PagingDTO pagingDTO = new PagingDTO(
                tableReqDTO.getPageNo(),
                tableReqDTO.getPageSize(),
                count,
                projectMapper.listUserProject(
                        userId,
                        tableReqDTO.parseQueryParam("projectName"),
                        tableReqDTO.parseQueryParam("sponsor"),
                        tableReqDTO.parseQueryParam("type"),
                        tableReqDTO.parseQueryParam("subject"),
                        state,
                        tableReqDTO.getStart(),
                        tableReqDTO.getPageSize(),
                        tableReqDTO.getSortField(),
                        tableReqDTO.getSortOrder()));
        return new TableRspDTO(pagingDTO);
    }

    @Override
    public  OpResultDTO addProject(String sponsor, ProjectDTO projectDTO) throws Exception {
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        ProjectEntity projectEntity = mapperFactory.getMapperFacade().map(projectDTO, ProjectEntity.class);
        op.setResult(projectMapper.addProject(projectEntity, sponsor, date));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO updateProject(ProjectDTO projectDTO) throws Exception {
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        ProjectEntity projectEntity = mapperFactory.getMapperFacade().map(projectDTO, ProjectEntity.class);
        op.setResult(projectMapper.updateProject(projectEntity,date));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO deleteProject(ProjectDTO projectDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        ProjectEntity projectEntity = mapperFactory.getMapperFacade().map(projectDTO, ProjectEntity.class);
        op.setResult(projectMapper.deleteProject(projectEntity));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO update(ProjectDTO projectDTO) throws Exception {
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        ProjectEntity projectEntity = mapperFactory.getMapperFacade().map(projectDTO, ProjectEntity.class);
        op.setResult(projectMapper.update(projectEntity,date));
        return op;
    }

    @Override
    public TableRspDTO listByProject(TableReqDTO tableReqDTO) throws Exception {
        String projectIdStr = tableReqDTO.parseQueryParam("projectId");
        PagingDTO pagingDTO;
        if (projectIdStr == null) {
            throw new IllegalArgumentException("Lose projectId");
        } else {
            Long projectId = Long.valueOf(projectIdStr);
            Long count = projectMapper.countByProject(
                    projectId,
                    tableReqDTO.parseQueryParam("candidateName")
            );
            pagingDTO = new PagingDTO(
                    tableReqDTO.getPageNo(),
                    tableReqDTO.getPageSize(),
                    count,
                    projectMapper.listByProject(
                            tableReqDTO.parseQueryParam("candidateName"),
                            projectId,
                            tableReqDTO.getStart(),
                            tableReqDTO.getPageSize(),
                            tableReqDTO.getSortField(),
                            tableReqDTO.getSortOrder()));
            return new TableRspDTO(pagingDTO);
        }
    }

    @Override
    public TableRspDTO queryAllProject(TableReqDTO tableRepDTO) throws Exception {
        String projectIdStr = tableRepDTO.parseQueryParam("projectId");
        PagingDTO pagingDTO;
        if (projectIdStr == null) {
            throw new IllegalArgumentException("Lose projectId");
        } else {
            Long projectId = Long.valueOf(projectIdStr);
            Long count = projectMapper.countAllProject(
                    tableRepDTO.parseQueryParam("userName")
            );
            pagingDTO = new PagingDTO(
                    tableRepDTO.getPageNo(),
                    tableRepDTO.getPageSize(),
                    count,
                    projectMapper.listAllProject(
                            tableRepDTO.parseQueryParam("userName"),
                            projectId,
                            tableRepDTO.getStart(),
                            tableRepDTO.getPageSize(),
                            tableRepDTO.getSortField(),
                            tableRepDTO.getSortOrder()));
            return new TableRspDTO(pagingDTO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO removeUserProject(UPDTO upDTO) throws Exception {
        OpResultDTO opResultDTO = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        UPEntity upEntity = mapperFactory.getMapperFacade().map(upDTO, UPEntity.class);
        opResultDTO.setResult(projectMapper.removeByProject(upEntity));
        return opResultDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO addByProject(UPDTO upDTO) throws Exception {
        OpResultDTO opResultDTO = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        UPEntity upEntity = mapperFactory.getMapperFacade().map(upDTO,UPEntity.class);
        upEntity.setVoted(0);
        opResultDTO.setResult(projectMapper.addByProject(upEntity));
        return opResultDTO;
    }

    @Override
    public List<PasswordDTO> listAllProject4Download(TableReqDTO tableRepDTO) throws Exception {
        String projectIdStr = tableRepDTO.parseQueryParam("projectId");
        PagingDTO pagingDTO;
        if (projectIdStr == null) {
            throw new IllegalArgumentException("Lose projectId");
        } else {
            Long projectId = Long.valueOf(projectIdStr);
            Long count = projectMapper.countAllProject(
                    tableRepDTO.parseQueryParam("userName")
            );
            return projectMapper.listAllProject4Download(
                    tableRepDTO.parseQueryParam("userName"),
                    projectId,
                    tableRepDTO.getStart(),
                    tableRepDTO.getPageSize(),
                    tableRepDTO.getSortField(),
                    tableRepDTO.getSortOrder());
        }
    }
}
